home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / plane / _Segment1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  5.8 KB  |  266 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _Segment1.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. //#include <LEDA/line.h>
  17.  
  18. #ifdef AMIGA
  19. #    include <LEDA/_Segment1.h>
  20. #else
  21. #    include <LEDA/Segment1.h>
  22. #endif
  23. #include <math.h>
  24. #include <ctype.h>
  25.  
  26. //static const double eps = 1e-10;
  27.  
  28.  
  29. //------------------------------------------------------------------------------
  30. // Segments 
  31. //------------------------------------------------------------------------------
  32.  
  33. Segment_rep::Segment_rep()  { count = 1; }
  34.  
  35. Segment_rep::Segment_rep(const Point& p, const Point& q) 
  36. { start = p;
  37.   end   = q;
  38.   dx = q.X()*p.W() - p.X()*q.W();
  39.   dy = q.Y()*p.W() - p.Y()*q.W();
  40.   count = 1; 
  41.     
  42. }
  43.   
  44.  
  45.  
  46. Segment::Segment() { PTR = new Segment_rep; }
  47.  
  48. Segment::Segment(const Point& x, const Point& y) 
  49. { PTR = new Segment_rep(x,y); }
  50.  
  51. Segment::Segment(const Int& x1, const Int& y1, const Int& x2, const Int& y2) 
  52. { PTR = new Segment_rep(Point(x1,y1), Point(x2,y2)); }
  53.  
  54.  
  55. /*
  56. Segment::Segment(const Point& p, double alpha, double length)
  57. { Point q = p.translate(alpha,length);
  58.   PTR  = new Segment_rep(p,q); 
  59.  }
  60.   
  61. Segment Segment::translate(double alpha, double d) const
  62. { Point p = ptr()->start.translate(alpha,d);
  63.   Point q = ptr()->end.translate(alpha,d);
  64.   return Segment(p,q);
  65.  }
  66.  
  67. Segment Segment::translate(const vector& v) const
  68. { Point p = ptr()->start.translate(v);
  69.   Point q = ptr()->end.translate(v);
  70.   return Segment(p,q);
  71.  }
  72.  
  73. */
  74.  
  75.  
  76. ostream& operator<<(ostream& out, const Segment& s) 
  77. { out << "[" << s.start() << "===" << s.end() << "]"; 
  78.   return out;
  79.  } 
  80.  
  81. /*
  82. istream& operator>>(istream& in, Segment& s) 
  83. { int x1,x2,y1,y2; 
  84.   in >> x1 >> y1 >> x2 >> y2; 
  85.   s = Segment(Point(x1,y1),Point(x2,y2)); 
  86.   return in; 
  87.  } 
  88. */
  89.  
  90. istream& operator>>(istream& in, Segment& s) 
  91. { // syntax: {[} p {===} q {]}
  92.  
  93.   Point p,q; 
  94.   char c;
  95.  
  96.   do in.get(c); while (isspace(c));
  97.   if (c != '[') in.putback(c);
  98.  
  99.   in >> p;
  100.  
  101.   do in.get(c); while (isspace(c));
  102.   while (c== '=') in.get(c);
  103.   while (isspace(c)) in.get(c);
  104.   in.putback(c);
  105.  
  106.   in >> q; 
  107.  
  108.   do in.get(c); while (c == ' ');
  109.   if (c != ']') in.putback(c);
  110.  
  111.   s = Segment(p,q); 
  112.   return in; 
  113.  
  114.  } 
  115.  
  116.  
  117. /*
  118. double Segment::angle(const Segment& s) const
  119. {
  120.   double cosfi,fi,norm;
  121.   
  122.   double dx  = ptr()->end.ptr()->x - ptr()->start.ptr()->x; 
  123.   double dy  = ptr()->end.ptr()->y - ptr()->start.ptr()->y; 
  124.  
  125.   double dxs = s.ptr()->end.ptr()->x - s.ptr()->start.ptr()->x; 
  126.   double dys = s.ptr()->end.ptr()->y - s.ptr()->start.ptr()->y; 
  127.   
  128.   cosfi=dx*dxs+dy*dys;
  129.   
  130.   norm=(dx*dx+dy*dy)*(dxs*dxs+dys*dys);
  131.  
  132.   if (norm == 0) return 0;
  133.  
  134.   cosfi /= sqrt( norm );
  135.  
  136.   if (cosfi >=  1.0 ) return 0;
  137.   if (cosfi <= -1.0 ) return M_PI;
  138.   
  139.   fi=acos(cosfi);
  140.  
  141.   if (dx*dys-dy*dxs>0) return fi;
  142.  
  143.   return -fi;
  144.  
  145. }
  146.  
  147.  
  148. double Segment::distance(const Segment& s) const
  149. { if (angle(s)!=0) return 0;
  150.   return distance(s.ptr()->start);
  151.  }
  152.  
  153. double  Segment::distance() const
  154. { return distance(Point(0,0)); }
  155.  
  156. double Segment::distance(const Point& p) const
  157. { Segment s(ptr()->start,p);
  158.   double l = s.length();
  159.   if (l==0) return 0;
  160.   else return l*sin(angle(s));
  161.  }
  162.  
  163.  
  164. double  Segment::y_proj(double x)  const
  165. { return  ptr()->start.ptr()->y - ptr()->slope * (ptr()->start.ptr()->x - x); }
  166.  
  167. double  Segment::x_proj(double y)  const
  168. { if (vertical())  return  ptr()->start.ptr()->x;
  169.   return  ptr()->start.ptr()->x - (ptr()->start.ptr()->y - y)/ptr()->slope; }
  170.  
  171. */
  172.  
  173. bool Segment::intersection(const Segment& s, Point& inter) const
  174. /* decides whether |s| and |this| segment intersect and, if so, returns the
  175. intersection in |r|. It is assumed that both segments have non-zero length */
  176. Int px = ptr()->start.X();
  177. Int py = ptr()->start.Y();
  178. Int pw = ptr()->start.W();
  179.  
  180. Int qx = ptr()->end.X();
  181. Int qy = ptr()->end.Y();
  182. Int qw = ptr()->end.W();
  183.  
  184. Int spx = s.start().X();
  185. Int spy = s.start().Y();
  186. Int spw = s.start().W();
  187.  
  188. Int sqx = s.end().X();
  189. Int sqy = s.end().Y();
  190. Int sqw = s.end().W();
  191.  
  192. Int A = -(py*qw - qy*pw);
  193. Int B =   px*qw - qx*pw;
  194. Int C = -(px*qy - qx*py);
  195.  
  196.  
  197. Int Aprime = -(spy*sqw - sqy*spw);
  198. Int Bprime =   spx*sqw - sqx*spw;
  199. Int Cprime = -(spx*sqy - sqx*spy);
  200.  
  201. Int cx = -(B*Cprime - C*Bprime);
  202. Int cy =   A*Cprime - C*Aprime ;
  203. Int cw = -(A*Bprime - B*Aprime);
  204.  
  205. if (cw == 0) return false;   //same slope
  206.  
  207. inter = Point(cx,cy,cw);
  208.  
  209.  
  210. /* cw is non-zero. Its sign does not matter for the test to follow.
  211.  
  212.   
  213.   if (pX*cw < cx &&  qX*cw < cx ||  pX*cw > cx  && qX*cw > cx ||
  214.    spX*cw< cx && sqX*cw < cx || spX*cw > cx && sqX*cw > cx ||
  215.    pY*cw < cy &&  qY*cw < cy ||  pY*cw > cy  && qY*cw > cy ||
  216.    spY*cw< cy && sqY*cw < cy || spY*cw > cy && sqY*cw > cy)
  217.   return false;
  218. */
  219.  
  220. /* we still need to test whether inter lies on both segments. A point lies on a segment if it compares diffently with the two endpoints of the segment */
  221.  
  222. if ((compare(start(),inter) == compare(end(),inter)) ||
  223.  (compare(s.start(),inter) == compare(s.end(),inter)))
  224. return false;
  225.  
  226. return true;
  227. }
  228.  
  229.  
  230. bool Segment::intersection_of_lines(const Segment& s, Point& inter) const
  231.   /* decides whether the lines induced by |s| and |this| segment 
  232.      intersect and, if so, returns the intersection in |inter|. 
  233.      It is assumed that both segments have non-zero length
  234.    */
  235.   
  236.   Int w = dy()*s.dx() - dx()*s.dy();
  237.  
  238.   if (w == 0) return false;   //same slope
  239.  
  240.   Int c1 = X2()*Y1() - X1()*Y2();
  241.   Int c2 = s.X2()*s.Y1() - s.X1()*s.Y2();
  242.  
  243.   inter = Point(dx()*c2 - s.dx()*c1, dy()*c2 - s.dy()*c1, w);
  244.  
  245.   return true;
  246. }
  247.  
  248. /*
  249. Segment Segment::rotate(double alpha) const
  250. {  double  l = length();
  251.    Point p = start();
  252.    double beta = alpha + angle();
  253.    return Segment(p,beta,l);
  254. }
  255.  
  256. Segment Segment::rotate(const Point& origin, double alpha) const
  257. {  Point p = start().rotate(origin,alpha);
  258.    Point q = end().rotate(origin,alpha);
  259.    return Segment(p,q);
  260. }
  261. */
  262.  
  263.